﻿using System;
using UnityEngine;

namespace Game
{
    public class SceneCameraComponent : ISceneComponent
    {
        private Transform _cameraTransform;
        private Camera _camera;
        private Bounds _sceneBounds;
        private Bounds _cameraBounds;
        private SceneObjectEntity _trackSceneObject;
        
        public SceneCameraComponent()
        {
        }
        
        public void Dispose()
        {
        }

        public void Setup(Camera camera, Bounds sceneBounds)
        {
            _camera = camera;
            _cameraTransform = camera.transform;
            _sceneBounds = sceneBounds;
            Vector3 cameraExtents = sceneBounds.extents;
            cameraExtents.x = cameraExtents.y * _camera.aspect;
            _cameraBounds.extents = cameraExtents;
            _camera.orthographicSize = _cameraBounds.extents.y;
        }

        public void SetTrackEntity(SceneObjectEntity sceneObject)
        {
            _trackSceneObject = sceneObject;
            UpdateTrack(0f);
        }
        
        public void Update(float deltaTime)
        {
            UpdateTrack(deltaTime);
        }

        private void UpdateTrack(float deltaTime)
        {
            Vector3 trackPosition = _trackSceneObject.position;
            Vector3 cameraPosition = _cameraTransform.position;
            Vector2 trackOffset = SceneConst.CameraTrackOffset;
            if (_trackSceneObject.GetFlipX())
            {
                trackOffset.y = -trackOffset.y;
            }

            if (_trackSceneObject.GetFlipY())
            {
                trackOffset.x = -trackOffset.x;
            }
            
            Vector2 deltaPosition = (Vector2)trackPosition + trackOffset - (Vector2)cameraPosition;
            if (deltaTime > 0f)
            {
                float moveLength = deltaTime * SceneConst.CameraTrackSpeed;
                if (Math.Abs(deltaPosition.x) > moveLength)
                {
                    deltaPosition.x = deltaPosition.x >= 0 ? moveLength : -moveLength;
                }
                if (Math.Abs(deltaPosition.y) > moveLength)
                {
                    deltaPosition.y = deltaPosition.y >= 0 ? moveLength : -moveLength;
                }   
            }
            
            cameraPosition.x += deltaPosition.x;
            cameraPosition.y += deltaPosition.y;
            if (cameraPosition.x - _cameraBounds.extents.x < _sceneBounds.center.x - _sceneBounds.extents.x)
            {
                cameraPosition.x = _sceneBounds.center.x - _sceneBounds.extents.x + _cameraBounds.extents.x;
            }
            else if (cameraPosition.x + _cameraBounds.extents.x > _sceneBounds.center.x + _sceneBounds.extents.x)
            {
                cameraPosition.x = _sceneBounds.center.x + _sceneBounds.extents.x - _cameraBounds.extents.x;
            }
            
            if (cameraPosition.y - _cameraBounds.extents.y < _sceneBounds.center.y - _sceneBounds.extents.y)
            {
                cameraPosition.y = _sceneBounds.center.y - _sceneBounds.extents.y + _cameraBounds.extents.y;
            }
            else if (cameraPosition.y + _cameraBounds.extents.y > _sceneBounds.center.y + _sceneBounds.extents.y)
            {
                cameraPosition.y = _sceneBounds.center.y + _sceneBounds.extents.y - _cameraBounds.extents.y;
            }
            _cameraTransform.position = cameraPosition;
        }
    }
}